package concurrentprogrammingchat.tuplespaces;

import java.util.*;

public class LocalTupleSpace implements TupleSpace {
	
	//We only need 2 attributes :
	// An array of tuples, of course
	private static ArrayList<String[]> Tuples;
	//And an ID, so we can  store the Tuple Space information into a tuple space.
	public static int TupleSpaceNumber = 0;
	private int TupleSpaceID;


	public LocalTupleSpace()
	{
		Tuples = new ArrayList<String[]>();
		LocalTupleSpace.TupleSpaceNumber = TupleSpaceNumber ++;
		TupleSpaceID = TupleSpaceNumber;
	}
	
    public int getTupleSpaceID() {
		return TupleSpaceID;
	}

    //The get method finds a matching tuple to the pattern and returns it.
	public String[] get(String[] pattern) {
    	if(pattern != null)
    	{
    		//This while loop ensure that you never leave unless you found the right tuple
    		while(true)
    		{
    			//We use a synchronize statement while accessing the Tuples ArrayList, 
    			//to ensure that there is no more than one process getting the same Tuple.
    				synchronized(this) {
    			    for(int i=0;i<Tuples.size();i++)
    				
    			    	//The lengths have first to be the same, the we compare the Strings one by one.
    					if(Tuples.get(i).length == pattern.length){
    						boolean isMatching = true;
        	    			for(int j=0;j<Tuples.get(i).length && isMatching;j++){
        	    				isMatching = (pattern[j] == null) || 
        	       				              pattern[j].equals(Tuples.get(i)[j]);
        	    			}
    		    			if(isMatching)
    		    			{
    		    				//Once we found the tuple we have to remove it from the list.
    	    					String[] returnTuple = Tuples.get(i);
    		    				Tuples.remove(i);	
    	    					return returnTuple;
    		    			}
    					}
	    			}
    				//If we did not find it, just wait(). You will be Notify() when another tuple will be added.
	    		synchronized(this)
	    		{
	    			try
	    			{
	    				this.wait();
	    			}
	    			catch(Exception e)
	    			{
	    				System.err.println("exception caught during wait");
	    			}
	    		}
    		}
    	}
    	else
    	{
    		System.err.println("Warning! String[] you're trying to get from Tuple Space is null!");
    		return pattern;
    	}
    }

	//The put method is very simple. It NotifyAll(), because all the waiting processes have to be warned about the new tuple.
    public void put(String[] tuple) {
    	synchronized(this)
    	{
    		Tuples.add(tuple);
    		try
    		{
    			this.notifyAll();
    		}
    		catch(Exception e) {}
    	}

    }
}
